package com.sytc.camera.uicontroller;

import com.sytc.camera.usb.OperateUsb;
import com.sytc.camera.util.MyRuntimeException;
import com.sytc.camera.util.RUN_STATE;
import com.sytc.camera.util.Util;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.geometry.Point2D;
import javafx.scene.Cursor;
import javafx.scene.control.*;
import javafx.scene.control.Label;
import javafx.scene.image.ImageView;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import javafx.util.Duration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.io.File;
import java.util.ArrayList;
import java.util.List;



@Component
public class MainuiController {


    private static final Logger log = LoggerFactory.getLogger(MainuiController.class);
    @FXML
    public Label vline;
    @FXML
    public Slider speedSlider;
    @FXML
    public Label reRileRun;
    @FXML
    public ProgressBar fileProcessBar;


    @Autowired
    OperateUsb operateUsb;
    @Autowired
    private ApplicationContext applicationContext;

    @FXML
    Label fileRun;
    @FXML
    CheckBox saveDatToFileBox;
    @FXML
    Tooltip selectedFileTooltip;
    @FXML
    public ImageView mainImage;
    @FXML
    public Label reLoadDevices;
    @FXML
    HBox runbox;
    @FXML
    Label run;
    @FXML
    ComboBox deviceBox;
    @FXML
    SplitPane rootPane;
    @FXML
    AnchorPane headPane;
    @FXML
    HBox hbox;
    @FXML
    Label logo;
    @FXML
    Label title;
    @FXML
    Label min;
    @FXML
    Label max;
    @FXML
    Label close;
    @FXML
    Label USB;
    @FXML
    Label file;
    @FXML
    GridPane usbGrid;
    @FXML
    GridPane fileGrid;
    @FXML
    Label selectFile;
    @FXML
    Label selectedFile;
    private double originalWidth;
    private double originalHeight;
    private double originalX;
    private double originalY;


    @FXML
    public void initialize() {

        operateUsb.setMainuiController(this);

        // 设置样式
        setStyle();

        // 设置为可改变大小
        changeSize();

        // 设置为可移动
        move();

        // 其它设置，比如监听
        otherSet();

        // 启动时就获取设备
        onReLoadDevices();

    }

    private void otherSet() {


    }

    // 处理窗口关闭事件
    public void onWindowClose(WindowEvent event) {
        log.info("窗口关闭事件");
        operateUsb.closeDevice();
        operateUsb.deleteOject();
        operateUsb.closePool();
        operateUsb.closeFile();
        // 关闭springboot
        SpringApplication.exit(applicationContext, () -> 0);
    }

    private void setStyle() {

        /* 设置主界面默认样式 */
        rootPane.getStylesheets().add(this.getClass().getResource("/ui/css/template.css").toExternalForm());
        rootPane.getStylesheets().add(this.getClass().getResource("/ui/css/other.css").toExternalForm());

        /* 设置标题栏样式 */
        // 添加样式表,加载后自己和子类都可以用
        rootPane.getStylesheets().add(this.getClass().getResource("/ui/css/head.css").toExternalForm());
        logo.setText("");
        title.setText("上海银心科技有限公司");
        min.setText("");
        max.getStyleClass().add("max");
        max.setText("");
        close.setText("");

        /* 设置运行or停止栏样式 */
        rootPane.getStylesheets().add(this.getClass().getResource("/ui/css/runbox.css").toExternalForm());
        run.getStyleClass().add("toStop");run.setText("");
        fileRun.getStyleClass().add("toRun");fileRun.setText("");

        /* 其它零碎样式 */
        reLoadDevices.getStyleClass().add("label-could-click");
        reLoadDevices.setText("刷新列表");
        selectFile.getStyleClass().add("label-could-click");

        USB.setText("");
        file.setText("");
        vline.setText("");
        reRileRun.setText("");


        // 鼠标悬停多久进行提示，放不到css里，只能这样弄
        selectedFileTooltip.setShowDelay(Duration.millis(100));  // 设置显示延迟为 100 毫秒
        selectedFileTooltip.setHideDelay(Duration.millis(100));  // 设置隐藏延迟为 100 毫秒
    }

    private void move() {
        // 创建一个数组来共享数据
        double[] mouseX = new double[1];  // 存储鼠标 X 坐标
        double[] mouseY = new double[1];  // 存储鼠标 Y 坐标
        Point2D[] panePoint = new Point2D[1];  // 存储 rootPane 的位置

        // 鼠标按下事件
        headPane.setOnMousePressed(event -> {
            mouseX[0] = event.getScreenX();  // 设置鼠标按下时的屏幕坐标
            mouseY[0] = event.getScreenY();
            panePoint[0] = rootPane.localToScreen(rootPane.getLayoutX(), rootPane.getLayoutY()); // 获取 rootPane 的位置
        });

        // 鼠标拖动事件
        headPane.setOnMouseDragged(event -> {
            Stage stage = (Stage) rootPane.getScene().getWindow();

            // 计算窗口的新位置
            stage.setX(event.getScreenX() - mouseX[0] + panePoint[0].getX());
            stage.setY(event.getScreenY() - mouseY[0] + panePoint[0].getY());
        });
    }

    private void changeSize() {
        // 鼠标移动到边缘时变为拖拽样式
        rootPane.setOnMouseMoved(event -> {
            double width = rootPane.getWidth();
            double height = rootPane.getHeight();
            double mouseX = event.getScreenX();
            double mouseY = event.getScreenY();
            Point2D panePoint = rootPane.localToScreen(rootPane.getLayoutX(), rootPane.getLayoutY());

            // 判断下边缘
            if (mouseY >= panePoint.getY() + height - 2 && mouseY <= panePoint.getY() + height) {
                // 右下角
                if (mouseX >= panePoint.getX() + width - 5) {
                    rootPane.setCursor(Cursor.SE_RESIZE); // 右下角拖动
                } else {
                    rootPane.setCursor(Cursor.S_RESIZE); // 下边拖动
                }
            }
            // 判断右边缘
            else if (mouseX >= panePoint.getX() + width - 2 && mouseX <= panePoint.getX() + width) {
                rootPane.setCursor(Cursor.E_RESIZE); // 右边拖动
            } else {
                rootPane.setCursor(Cursor.DEFAULT); // 恢复默认光标
            }
        });

        // 鼠标拖动事件
        rootPane.setOnMouseDragged(event -> {
            // 如果鼠标不是默认，不处理
            if(rootPane.getCursor() == Cursor.DEFAULT)
                return;

            Stage stage = (Stage) rootPane.getScene().getWindow();
            Point2D panePoint = rootPane.localToScreen(rootPane.getLayoutX(), rootPane.getLayoutY());

            /* 根据不同的鼠标光标调整窗口大小 */
            // 右边拖动
            if (rootPane.getCursor() == Cursor.E_RESIZE) {
                stage.setWidth(event.getScreenX() - panePoint.getX());
            }
            // 下边拖动
            else if (rootPane.getCursor() == Cursor.S_RESIZE) {
                stage.setHeight(event.getScreenY() - panePoint.getY());
            }
            // 右下角拖动
            else if (rootPane.getCursor() == Cursor.SE_RESIZE) {
                stage.setWidth(event.getScreenX() - panePoint.getX());
                stage.setHeight(event.getScreenY() - panePoint.getY());
            }
        });
    }

    public void onMin(MouseEvent mouseEvent) {
        Stage stage = (Stage) rootPane.getScene().getWindow();
        stage.setIconified(true);
    }

    public void onClose(MouseEvent mouseEvent) {
        Stage stage = (Stage) rootPane.getScene().getWindow();
        stage.close();
    }

    public void onMax(MouseEvent mouseEvent) {
        Stage stage = (Stage) rootPane.getScene().getWindow();
        // 检查窗口是否已经最大化
        if (stage.isMaximized()) {
            // 如果窗口已经最大化，则恢复原始大小和位置
            stage.setMaximized(false);
            stage.setWidth(originalWidth);
            stage.setHeight(originalHeight);
            stage.setX(originalX);
            stage.setY(originalY);
            max.getStyleClass().removeAll("max-min");
            max.getStyleClass().add("max");
        } else {
            // 如果窗口没有最大化，保存当前窗口大小和位置，并最大化窗口
            originalWidth = stage.getWidth();
            originalHeight = stage.getHeight();
            originalX = stage.getX();
            originalY = stage.getY();
            stage.setMaximized(true);
            max.getStyleClass().removeAll("max");
            max.getStyleClass().add("max-min");
        }
    }

    public void onRunUSB(MouseEvent mouseEvent) {

        operateUsb.setUsbRunning(false); // 只要点击了就让以前的程序停下来
        operateUsb.setFileState(RUN_STATE.STOPPED); // 只要点击了就让以前的程序停下来

        // 图标是run的时候，本身是停止的，run图标是提示用户点击后开始运行
        if (run.getStyleClass().contains("toStop")) {
            run.getStyleClass().removeAll("toStop");
            run.getStyleClass().add("toRun");
        }
        // 运行
        else {
            run.getStyleClass().removeAll("toRun");
            run.getStyleClass().add("toStop");
            runUsb(null); // 运行已选择的设备

        }
    }

    /**
     * 文件的运行，暂停
     */
    public void onRunFile(MouseEvent mouseEvent) {

        operateUsb.setUsbRunning(false); // 只要点击了就让usb停下来

        // 图标是run的时候，本身是停止的，run图标是提示用户点击后开始运行
        if (fileRun.getStyleClass().contains("toStop")) {
            fileRun.getStyleClass().removeAll("toStop");
            fileRun.getStyleClass().add("toRun");
            operateUsb.setFileState(RUN_STATE.PAUSED); // 先暂停
        }
        // 运行
        else {
            fileRun.getStyleClass().removeAll("toRun");
            fileRun.getStyleClass().add("toStop");
            // 如果是暂停状态，就解冻
            if((null != operateUsb.getRunFileTread()) && (Thread.State.RUNNABLE == operateUsb.getRunFileTread().getState())){
                operateUsb.setFileState(RUN_STATE.RUNNING); // 先暂停
            }else {
                runFile();
            }
        }

    }

    /**
     * 文件的重新运行
     */
    public void onReRunFile(MouseEvent mouseEvent) {
        operateUsb.setUsbRunning(false); // 只要点击了就让以前的程序停下来
        operateUsb.setFileState(RUN_STATE.STOPPED); // 只要点击了就让以前的程序停下来
        // 这句很关键，必须要等到上一个线程停止才可以，这句也很快，毫秒级别
        if(null != operateUsb.getRunFileTread()){
            try {
                operateUsb.getRunFileTread().join();
            } catch (InterruptedException e) {
                log.error("线程{}没有正常关闭", operateUsb.getRunFileTread());
            }
        }
        fileRun.getStyleClass().removeAll("toRun");
        fileRun.getStyleClass().add("toStop");
        runFile(); // 运行已选择的文件
    }


    public void runUsb(ActionEvent actionEvent) {

        int deviceIndex = deviceBox.getSelectionModel().getSelectedIndex();
        log.info("选择了设备"+deviceIndex+" "+deviceBox.getSelectionModel().getSelectedItem());

        try {
            // 先关闭，再打开，用来切换设备
            operateUsb.closeDevice();
            operateUsb.open(deviceIndex);
            operateUsb.setUsbRunning(true);
            operateUsb.usbBeginGetData();
            operateUsb.usbBeginDividePackage();
            operateUsb.usbBeginOperateImage();
            operateUsb.usbShowImage();
        } catch (MyRuntimeException e) {
            // 显示提示框
            Util.errorAlert(e.getMessage());
        }


    }

    public void runFile() {

        // 创建 File 对象
        File file = new File(selectedFile.getText());
        // 判断文件是否存在
        if (!file.exists()) {
           Util.errorAlert("文件不存在："+selectedFile.getText());
           onRunFile(null);
           return;
        }

        try {
            operateUsb.setFileState(RUN_STATE.RUNNING);
            operateUsb.fileBeginAll(selectedFile.getText());
        }catch (MyRuntimeException e) {
            // 显示提示框
            Util.errorAlert(e.getMessage());
        }


    }



    @FXML
    public void onReLoadDevices() {

        // 后台线程完成设备数据加载
        List<String> deviceNames = new ArrayList<>();
        try {
            deviceNames.addAll(operateUsb.getDevices());  // 加载设备数据
        } catch (MyRuntimeException e) {
            // 显示提示框
            Util.errorAlert(e.getMessage());
        }

        // 更新 ComboBox 的数据
        deviceBox.getItems().setAll(deviceNames);
        if (!deviceNames.isEmpty()) {
            deviceBox.setValue(deviceNames.get(0));  // 设置默认值
            runUsb(null); // 选择后直接开始运行
        }else{
            deviceBox.setValue("没有设备");  // 设置默认显示文本
        }

    }

    public void onUSB(MouseEvent mouseEvent) {
        usbGrid.setVisible(true);
        fileGrid.setVisible(false);
    }

    public void onFile(MouseEvent mouseEvent) {
        fileGrid.setVisible(true);
        usbGrid.setVisible(false);
    }





    public void onSelectFile(MouseEvent mouseEvent) {

        // 创建 FileChooser 实例
        FileChooser fileChooser = new FileChooser();

        // 设置文件扩展名过滤器（可选）
        fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("dat文件", "*.dat"));
        fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("所有文件", "*.*"));

        // 设置默认打开路径为程序所在路径
        fileChooser.setInitialDirectory(new File(System.getProperty("user.dir")+"/out/datfile"));  // 设置初始路径为当前工作目录

        // 打开文件选择对话框
        File file = fileChooser.showOpenDialog(rootPane.getScene().getWindow());

        if (file != null) {
           selectedFile.setText(file.getAbsolutePath());
           selectedFileTooltip.setText("单击可以复制路径：\n" + file.getAbsolutePath());

            // 只要选择了文件就让usb停下来
            operateUsb.setUsbRunning(false);
            // 只要选择了文件，就变成运行
            fileRun.getStyleClass().removeAll("toRun");
            fileRun.getStyleClass().add("toStop");
            // 只要选择了文件，就让file停下来，重新开始
            operateUsb.setFileState(RUN_STATE.STOPPED);
            // 一直等到线程结束
            if(null != operateUsb.getRunFileTread()){
                try {
                    operateUsb.getRunFileTread().join();
                } catch (InterruptedException e) {
                    log.error("线程{}没有正常关闭", operateUsb.getRunFileTread());
                }
            }
            runFile();
        }
    }

    public void onCopyFilePath(MouseEvent mouseEvent) {
        // 创建 ClipboardContent 对象
        ClipboardContent content = new ClipboardContent();
        content.putString(selectedFile.getText());
        // 获取系统剪贴板并设置文本
        Clipboard.getSystemClipboard().setContent(content);
    }


    public void onSaveDatToFile(MouseEvent mouseEvent) {
        if (saveDatToFileBox.isSelected()) {
            operateUsb.createNewFile();
        } else {
            operateUsb.closeFile();
        }
    }


    public void onChangeProgress(MouseEvent mouseEvent) {
        // 获取鼠标点击的位置
        double clickX = mouseEvent.getX();
        // 获取进度条的宽度
        double width = fileProcessBar.getWidth();
        // 计算并设置进度
        double progress = clickX / width;
        fileProcessBar.setProgress(progress);
        operateUsb.setNewFileProgress(progress);
    }

    public void onImage(MouseEvent mouseEvent) {
    }

    public void onNUC(MouseEvent mouseEvent) {
    }

    public void onBackgroundDiff(MouseEvent mouseEvent) {
    }

    public void onBasicInfo(MouseEvent mouseEvent) {
    }

    public void onNormalized(MouseEvent mouseEvent) {
    }

    public void onSelectAll(MouseEvent mouseEvent) {
    }

    public void onSaveImageConfig(MouseEvent mouseEvent) {
    }

    public void onLoadImageConfig(MouseEvent mouseEvent) {

    }
}
